/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Actor;

import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;
import projectshanghai.World;

/**
 *
 * @author Eric-Standard
 */
public abstract class Actor {

    //The position of this actor
    protected Point2d pos;
    //Pixels per second
    protected Vector2d vel;
    protected World world;
    //Angle in radians, right is 0.0
    protected double angle = -Math.PI / 2;
    //Flags
    //This flag indicates whether the Actor will be drawn
    public boolean isDrawn = true;
    public boolean collisionDetection = true;
    //If this flag is false, the Actor will be removed from the world
    public boolean isActive = true;
    //Prevent unnecessary new objects
    public static final Point2d DEFAULT_POINT = new Point2d(0, 0);
    public static final Vector2d DEFAULT_VEL = new Vector2d(0, 0);
    private Vector2d scaledVel;

    /**
     * Constructs a new Actor with the default location and velocity.
     */
    public Actor() {
        this(DEFAULT_POINT, DEFAULT_VEL);
    }

    /**
     * Constructs a new Actor with the location and default velocity.
     *
     * @param p
     */
    public Actor(Point2d p) {
        this(p, DEFAULT_VEL);
    }

    /**
     * Constructs a new Actor with the specified location and velocity.
     *
     * @param p
     * @param v
     */
    public Actor(Point2d p, Vector2d v) {
        pos = new Point2d(p);
        vel = new Vector2d(v);
        scaledVel = new Vector2d();
    }

    /**
     * Draws an actor on the Graphics context.
     *
     * @param g
     */
    public void draw(Graphics g) {
    }

    /**
     * Steps this actor.
     *
     * @param dt
     */
    public void act(long dt) {
        if (vel.x == 0 && vel.y == 0) {
            return;
        }
        scaledVel.x = vel.x;
        scaledVel.y = vel.y;
        scaledVel.scale(dt / 1000.0);
        pos.add(scaledVel);
    }

    /**
     * Puts this actor in the world. <b>This method should not be called
     * directly.</b> Use the World.add() method instead.
     *
     * @param world
     */
    public void putSelfInWorld(World world) {
        setWorld(world);
    }

    /**
     * Gets the velocity of this actor.
     * @return 
     */
    public Vector2d getVel() {
        return vel;
    }

    /**
     * Sets the world of this actor.
     *
     * @param world
     */
    public void setWorld(World world) {
        this.world = world;
    }

    /**
     * Removes this actor from the world. This method sets the isActive flag to
     * false.
     */
    public void removeSelfFromWorld() {
        this.isActive = false;
    }

    /**
     * Gets the position of this actor.
     *
     * @return
     */
    public Point2d getPos() {
        return pos;
    }

    /**
     * Sets the position of this actor.
     *
     * @param point
     */
    public void setPos(Point2d point) {
        this.pos = point;
    }

    /**
     * Gets the angle of this actor.
     *
     * @return
     */
    public double getAngle() {
        return angle;
    }

    /**
     * Set the angle of this actor.
     *
     * @param angle
     */
    public void setAngle(double angle) {
        this.angle = angle;
    }

    /**
     * Gets the world of this actor.
     *
     * @return
     */
    public World getWorld() {
        return world;
    }

    /**
     * Gets a bounding rectangle for this actor. This method <b>may</b> still be
     * called even if collisionDetection is false.
     *
     * @return
     */
    public abstract Rectangle2D getBoundingRectangle();

    /**
     * Gets the area that this actor occupies. This method will not be called if
     * collisionDetection is false.
     *
     * @return
     */
    public abstract Area getArea();

    /**
     * Indicates a collision with a Shape.
     *
     * @param shape
     */
    public void collide(Shape shape) {
    }

    /**
     * Indicates a collision with a TileObject.
     *
     * @param tileObject
     */
    public void collide(TileObject tileObject) {
    }

    /**
     * Indicates a collision with a Actor.
     *
     * @param actor
     */
    public void collide(Actor actor) {
    }
}
